grammar Program;

// Parser

prog	:	statement* ;
statement
	:	BRACKET_CENTIPOISE_LEFT statement* BRACKET_CENTIPOISE_RIGHT
	|	localVariableDeclaration SEMICOLON
	|	IF parExpression statement (ELSE statement)?
	|	DO statement WHILE parExpression SEMICOLON
	|	SEMICOLON
	|	statementExpression SEMICOLON
	|	GOTO label SEMICOLON
	|	label COLON statement
	|	typeDeclarationStatement SEMICOLON
	;
label	:	IDENTIFIER;
typeDeclarationStatement
	:	TYPE IDENTIFIER ASSIGN type
	;
localVariableDeclaration
	:	type variableDeclarators
	;
type	:	primitiveType
	|	customType
	;
primitiveType
	:	INT
	|	FLOAT
	|	TYPE_RATIONAL
	|	BOOLEAN
	|	VECTOR
	;
customType
	:	IDENTIFIER
	;
variableDeclarators
	:	variableDeclarator (COMMA variableDeclarator)*
	;
variableDeclarator
	:	variableDeclaratorId (ASSIGN expression)?
	;
variableDeclaratorId
	:	IDENTIFIER
	;

parExpression
	:	BRACKET_LEFT conditionalExpression BRACKET_RIGHT
	;
statementExpression
	:	expression
	;
expression
	:	conditionalExpression (assignmentOperator expression)?
	;
assignmentOperator
	:	ASSIGN
	;
conditionalExpression
	:	equalityExpression
	;
equalityExpression
	:	relationalExpression ( (EQUAL | NOT_EQUAL) relationalExpression )*
	;
relationalExpression
	:	additiveExpression ( relationalOp additiveExpression )*
	;
relationalOp
	:	LE
	|	GE
	|	LT
	|	GT
	;
additiveExpression
	:	multiplicativeExpression ( (PLUS | MINUS) multiplicativeExpression )*
	;

multiplicativeExpression
	:	unaryExpression ( ( MULT | DIVIDE ) unaryExpression )*
	;
unaryExpression
	:	PLUS unaryExpression
	|	MINUS unaryExpression
	|	unaryExpressionNotPlusMinus
	;
unaryExpressionNotPlusMinus
	:	NOT unaryExpression
	|	brakesExpression
	|	primary
	;
brakesExpression
	:	BRACKET_LEFT type BRACKET_RIGHT unaryExpressionNotPlusMinus	// cast expression
	|	BRACKET_LEFT conditionalExpression BRACKET_RIGHT		// parenthesis expression
	;
primary
	:	IDENTIFIER (DOT IDENTIFIER)? identifierSuffix?
	|	vectorCreator
	|	literal
	|	function
	;
identifierSuffix
	:	BRACKET_SQUARE_LEFT expression BRACKET_SQUARE_RIGHT
	;
literal 
	:	DECIMAL
	|	FLOATING
	|	RATIONAL
	|	booleanLiteral
	|	NULL
	;
booleanLiteral
	:	TRUE
	|	FALSE
	;
vectorCreator
	:	NEW (VECTOR | customType) vectorCreatorRest
	;
vectorCreatorRest
	:	BRACKET_SQUARE_LEFT expression BRACKET_SQUARE_RIGHT
	|	BRACKET_SQUARE_LEFT BRACKET_SQUARE_RIGHT BRACKET_CENTIPOISE_LEFT ( expression (COLON expression)* )? BRACKET_CENTIPOISE_RIGHT
	;
function:	functionId BRACKET_LEFT arguments? BRACKET_RIGHT
	;
functionId
	:	IDENTIFIER
	;
arguments
	:	expression (COLON expression)*
	;

// Lexer

IDENTIFIER	
	:	('a'..'z' | 'A'..'Z') ('a'..'z' | 'A'..'Z' | '0'..'9')* ;
DECIMAL	:	('0'..'9')+ ;
FLOATING:	('0'..'9')+ '.' ('0'..'9')* ;
RATIONAL:	('0'..'9')+ '/' ('0'..'9')+ ;

WS	:	(' ' | '\t')  {$channel=HIDDEN; };

LINE_COMMENT
	:	'//' ~('\n' | '\r')* '\r'? '\n' {$channel=HIDDEN; };

// Symbols
BRACKET_LEFT
	:	'(';
BRACKET_RIGHT
	:	')';
BRACKET_CENTIPOISE_LEFT
	:	'{';
BRACKET_CENTIPOISE_RIGHT
	:	'}';
BRACKET_SQUARE_LEFT
	:	'[';
BRACKET_SQUARE_RIGHT
	:	']';

COLON	:	':';
SEMICOLON
	:	';';
COMMA	:	',';

// Operators
ASSIGN	:	'=';
NOT	:	'!';
DOT	:	'.';
EQUAL	:	'==';
NOT_EQUAL
	:	'!=';
LE	:	'<=';
LT	:	'<';
GE	:	'>=';
GT	:	'>=';

MULT	:	'*';
DIVIDE	:	'/';
PLUS	:	'+';
MINUS	:	'-';

// Predefined words
IF	:	'if';
ELSE	:	'else';
DO	:	'do';
WHILE	:	'while';
GOTO	:	'goto';
TYPE	:	'type';
NULL	:	'null';
TRUE	:	'true';
FALSE	:	'false';
NEW	:	'new';

// Types
INT	:	'int';
FLOAT	:	'float';
TYPE_RATIONAL:	'rational';
BOOLEAN	:	'boolean';
VECTOR	:	'vector';
